package com.seeyon.ctp.rest.resources;

import java.io.File;
import java.io.FileOutputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.seeyon.apps.brwh.abstraction.MultipartFileUtils;
import com.seeyon.apps.brwh.kit.FormCap4Kit;
import com.seeyon.apps.brwh.kit.StrKit;
import com.seeyon.apps.collaboration.manager.ColManager;
import com.seeyon.apps.collaboration.po.ColSummary;
import com.seeyon.apps.econtract.platform.params.output.TemplateListOutput.Data.list;
import com.seeyon.cap4.form.bean.FormBean;
import com.seeyon.cap4.form.bean.FormDataMasterBean;
import com.seeyon.cap4.form.service.CAP4FormManager;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.seeyon.apps.brwh.cn.hz.comm.EsignHttpResponse;
import com.seeyon.apps.brwh.cn.hz.exception.EsignDemoException;
import com.seeyon.apps.brwh.entity.FileMsgEntity;
import com.seeyon.apps.brwh.manager.SealManager;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.ctpenumnew.manager.EnumManager;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.common.filemanager.manager.AttachmentManager;
import com.seeyon.ctp.common.filemanager.manager.FileManager;
import com.seeyon.ctp.common.log.CtpLogFactory;
import com.seeyon.ctp.common.po.ctpenumnew.CtpEnumItem;
import com.seeyon.ctp.common.po.filemanager.V3XFile;
import com.seeyon.ctp.organization.bo.V3xOrgMember;
import com.seeyon.ctp.organization.manager.OrgManager;
import com.seeyon.ctp.organization.po.OrgMember;
import com.seeyon.ctp.services.FileDownloadExporter;
import com.seeyon.ctp.util.StringUtil;

/**
 * @author zgh
 * @version 1.0 Create by 2024/6/5 15:21
 */

@Path("/jssdk")
@Produces({"application/json"})
@Consumes({"application/json"})
public class SealResource extends BaseResource {

  private Log LOGGER = CtpLogFactory.getLog(SealResource.class);

  private static SealManager sealManager = (SealManager) AppContext.getBean("sealManager");
  private static CAP4FormManager cap4FormManager = (CAP4FormManager) AppContext.getBean("cap4FormManager");
  private static FileManager fileManager = (FileManager) AppContext.getBean("fileManager");
  private static AttachmentManager attachmentManager = (AttachmentManager) AppContext.getBean("attachmentManager");
  private static OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager");
  private static EnumManager enumManagerNew = (EnumManager) AppContext.getBean("enumManagerNew");

  private static ColManager colManager = (ColManager) AppContext.getBean("colManager");


  /**
   * (基于页面签署)通过HTML对PDF进行加签。 使用POST方法，通过提供的HTML内容对PDF文件进行电子签名初始化。 此方法主要负责调用加签管理器的相应方法，完成加签流程的初始化，并返回初始化成功的URL。
   *
   * @param fileMes 包含加签相关信息的Map对象，目前虽然传入为空，但预留了扩展性。
   * @return Response 对象，包含加签流程初始化成功的URL。
   * @throws EsignDemoException 如果加签过程出现错误，会抛出此异常。
   * @POST
   * @Path("/sealPdfByHtml")
   */
  public Response sealPdfByHtml(Map<String, Object> fileMes) throws EsignDemoException {
    // 记录日志，表示请求已进入
    LOGGER.info("请求已进入！");

    // 调用加签管理器的sealPdfByHtml方法，此处参数暂时为空，预留了扩展性
    EsignHttpResponse byFileName = sealManager.sealPdfByHtml("", "");

    // 解析加签管理器返回的响应体，获取加签流程初始化的URL
    JSONObject createByFileJsonObject = JSONObject.parseObject(byFileName.getBody());

    // 构建并返回响应，包含加签流程初始化成功的URL
    return this.ok(createByFileJsonObject.getJSONObject("data").getString("signFlowInitiateUrl"));
  }


  /**
   * (基于页面签署后回调)通过HTML方式回调消息。
   * <p>
   * 该方法用于接收外部系统通过HTML形式发送的回调消息。回调消息中可能包含签名状态、文档处理结果等信息。 方法通过解析回调消息中的数据，进行相应的业务处理。
   * </p>
   *
   * @param callBackMsg 回调消息的Map对象，其中包含了回调消息的具体内容。 Key为消息的名称，Value为消息的具体值。
   * @return 返回一个响应对象，表示接收回调消息的操作是否成功。
   * @throws EsignDemoException 如果处理回调消息过程中出现错误，会抛出此异常。
   * @POST 表示该方法用于处理HTTP POST请求。
   * @Path("/callBackMsgByHtml") 指定了该方法对应的RESTful API路径。
   */
  @POST
  @Path("/callBackMsgByHtml")
  public Response callBackMsgByHtml(Map<String, Object> callBackMsg) throws EsignDemoException {
    LOGGER.info("请求已进入！");
    return this.ok(null);
  }

  /**
   * (基于文件签署)通过文件对PDF进行加签测试。 此方法接收一个包含加签相关信息的Map对象，从其中提取必要信息，下载文件，并对文件进行加签操作。 最后返回加签结果的列表。
   *
   * @param map 包含加签所需信息的Map对象，如数据ID、应用ID、应用密钥等。
   * @return 返回加签结果的Response对象。
   * @throws Exception 如果加签过程中发生错误，抛出异常。
   */
  @POST
  @Path("/sealPdfByFile")
  @Consumes(MediaType.APPLICATION_JSON)
  public Response sealPdfByFile(Map<String, Object> map) throws Exception {
    List<Map<String, Object>> list = new ArrayList<>();
    Map<String, Object> resBadMap = new HashMap<>();
    // 日志记录传入的参数信息
    LOGGER.info(JSON.toJSONString(map));
    String clientIp = MultipartFileUtils.getClientIp(req);
    LOGGER.info(MultipartFileUtils.getClientIp(req));
    // 从map中提取数据ID，并转换为字符串
    String dataId = StrKit.str(map.get("dataId"));

    ColSummary  colSummary = colManager.getColSummaryByFormRecordId(Long.parseLong(dataId));
    FormBean formBean = cap4FormManager.getForm(colSummary.getFormAppid(), true);
    // 根据数据ID获取表单主数据对象
    FormDataMasterBean formDataMasterBean = cap4FormManager.getDataMasterBeanById(Long.parseLong(dataId), formBean, null);
    // 从formDataMasterBean中提取应用ID、应用密钥、企业名称等信息
    String appId = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "应用ID")).trim();
    LOGGER.info("应用ID:" + appId);
    String appSercet = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "应用密钥")).trim();
    LOGGER.info("应用密钥:" + appSercet);
    String orgName = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "签署方企业名称")).trim();
    LOGGER.info("签署方企业名称:" + orgName);
    String orgIDCardNum = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "签署方信用代码"));
    String psnAccount = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "签署方手机号")).trim();
    String psnName = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "签署方姓名")).trim();
    String file = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "签署文件")).trim();
    LOGGER.info("file文件Id:" + file);
    if (StringUtils.isEmpty(file)) {
      resBadMap.put("status", 500);
      resBadMap.put("msg", "文件获取不到");
      list.add(resBadMap);
      return this.ok(list);
    }
    String aSealLocation = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "甲方盖章位置")).trim();
    String bSealLocation = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "乙方盖章位置")).trim();
    String startSealName = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "发起方姓名")).trim();
    String startSealPhone = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "发起方手机号")).trim();
    String startOrgName = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "发起方企业名称")).trim();
    String startOrgIDCardNum = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "发起方信用代码")).trim();
    String otherFile = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "附属文件")).trim();
    // 根据正文文件ID获取附件列表
    List<Long> attachmentList = attachmentManager.getBySubReference(Long.parseLong(file));
    if (attachmentList.isEmpty()) {
      resBadMap.put("status", 500);
      resBadMap.put("msg", "文件列表获取为空");
      list.add(resBadMap);
      return this.ok(list);
    }
    // 构建文件下载的临时路径
    // 获取下载临时文件目录
    String filePath = AppContext.getCfgHome().getCanonicalPath();
    filePath = filePath.replace("WEB-INF" + File.separator + "cfgHome", "fileTemp" + File.separator);
    String basePath = filePath + File.separator;
    //保存文件临时下载路径
    List<File> fileList = new ArrayList<>();
    // 创建FileMsgEntity对象列表，用于存储加签文件及相关信息
    List<FileMsgEntity> fileMsgEntityList = new ArrayList<>();
    // 遍历附件列表，对每个文件进行加签操作
    for (Long num : attachmentList) {
      File newFile = new File(basePath + file + "_" +  fileManager.getV3XFile(num).getFilename());
      FileOutputStream out = new FileOutputStream(newFile.getPath());
      FileDownloadExporter downloadExporter = new FileDownloadExporter();
      downloadExporter.processDownload(fileManager.getV3XFile(num).getId() + "", out);
      // 将下载的文件转换为MultipartFile对象
      MultipartFile m = MultipartFileUtils.convert(newFile);
      // 创建FileMsgEntity对象，包含加签文件及相关信息
      FileMsgEntity fileMsg = new FileMsgEntity("", m, fileManager.getV3XFile(num).getFilename().trim(),
                                                appId.trim(), appSercet.trim(), orgName.trim(),
                                                orgIDCardNum.trim(), psnAccount.trim(),
                                                psnName.trim(), aSealLocation.trim(),
                                                bSealLocation.trim(), clientIp.trim(),
                                                startSealName.trim(), startSealPhone.trim(),
                                                startOrgName.trim(), startOrgIDCardNum.trim(), "1");
      fileMsgEntityList.add(fileMsg);
      fileList.add(newFile);
    }
    List<Long> otherFileList =new ArrayList<>();
    if (StringUtils.isNotBlank(otherFile)){
      otherFileList.addAll(attachmentManager.getBySubReference(Long.parseLong(otherFile)));
    }
    //附属文件
    for (Long num : otherFileList) {
      File newFile = new File(basePath + file + "_" + fileManager.getV3XFile(num).getFilename());
      FileOutputStream out = new FileOutputStream(newFile.getPath());
      FileDownloadExporter downloadExporter = new FileDownloadExporter();
      downloadExporter.processDownload(fileManager.getV3XFile(num).getId() + "", out);
      // 将下载的文件转换为MultipartFile对象
      MultipartFile m = MultipartFileUtils.convert(newFile);
      // 创建FileMsgEntity对象，包含加签文件及相关信息
      FileMsgEntity fileMsg = new FileMsgEntity("", m, fileManager.getV3XFile(num).getFilename().trim(),
                                                appId.trim(), appSercet.trim(), orgName.trim(),
                                                orgIDCardNum.trim(), psnAccount.trim(),
                                                psnName.trim(), aSealLocation.trim(),
                                                bSealLocation.trim(), clientIp.trim(),
                                                startSealName.trim(), startSealPhone.trim(),
                                                startOrgName.trim(), startOrgIDCardNum.trim(), "2");
      fileMsgEntityList.add(fileMsg);
      fileList.add(newFile);
    }
    // 调用加签服务，对文件进行加签
    Map<String, Object> resMap = sealManager.sealPdfByFile(fileMsgEntityList);
    list.add(resMap);
    if (!fileList.isEmpty()) {
      for (File onceFile : fileList) {
        // 删除临时文件
        if (onceFile.exists()) {
          if (onceFile.delete()) {
            LOGGER.info("文件已成功删除: " + onceFile.getName());
          } else {
            LOGGER.info("无法删除文件: " + onceFile.getName());
          }
        }
      }
    }
    // 返回加签结果
    return this.ok(list);
  }


  /**
   * 下载电子封签PDF文件。 该方法处理下载已签署完成的合同流程中的电子封签PDF文件的请求。 通过传入的dataId获取合同流程信息，并检查该流程是否已完成签署。 如果签署完成，则从电子封签管理服务获取下载链接并返回给调用者。 如果流程未完成签署，则返回错误信息。
   *
   * @param map 包含请求数据的Map，其中应包含dataId字段。
   * @return Response 对象，包含文件下载链接或错误信息。
   * @throws EsignDemoException 如果发生与电子签名相关的错误，则抛出此异常。
   */
  @POST
  @Path("/downLoadSealPdf")
  @Consumes(MediaType.APPLICATION_JSON)
  public Response downLoadSealPdf(Map<String, Object> map) throws EsignDemoException, BusinessException, SQLException {
    //    初始化用于存储文件下载信息的ListMap
    List<Map<String, Object>> resListMap = new ArrayList<>();
    Map<String, Object> fileMap = new HashMap<>();
    // 从请求参数中提取dataId
    String dataId = StrKit.str(map.get("dataId"));
    ColSummary  colSummary = colManager.getColSummaryByFormRecordId(Long.parseLong(dataId));
    FormBean formBean = cap4FormManager.getForm(colSummary.getFormAppid(), true);
    // 根据数据ID获取表单主数据对象
    FormDataMasterBean formDataMasterBean = cap4FormManager.getDataMasterBeanById(Long.parseLong(dataId), formBean, null);
    // 从流程数据中提取应用ID、应用密钥和合同流程ID
    String appId = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "应用ID")).trim();
    String appSercet = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "应用密钥")).trim();
    String signFlowId = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "合同流程ID")).trim();
    // 检查合同流程是否已完成签署
    if (StringUtils.isEmpty(signFlowId)) {
      // 如果未完成签署，则返回错误信息
      LOGGER.info("合同流程ID为空,无法进行下载");
      fileMap.put("msg", "合同流程ID为空,无法进行下载");
      fileMap.put("status", 500);
      resListMap.add(fileMap);
      return this.ok(resListMap);
    }
    // 初始化用于存储文件下载请求参数的Map
    Map<String, Object> fileDownloadMsg = new HashMap<>();
    // 设置下载请求的必要参数
    fileDownloadMsg.put("eSignAppId", appId.trim());
    fileDownloadMsg.put("eSignAppSecret", appSercet.trim());
    fileDownloadMsg.put("signFlowId", signFlowId.trim());
    // 调用电子封签管理服务下载PDF文件
    EsignHttpResponse esignHttpResponse = sealManager.downLoadSealPdf(fileDownloadMsg);
    // 解析服务响应获取下载链接信息
    JSONObject signUrlJson = JSONObject.parseObject(esignHttpResponse.getBody());
    // 解析下载链接信息
    JSONObject data = signUrlJson.getJSONObject("data");
    if (signUrlJson.getIntValue("code") == 0) {
      // 如果下载链接信息获取成功，则处理下载链接
      if (data.getJSONArray("files") != null) {
        JSONArray keywordPositions = data.getJSONArray("files");
        List<Map<String, Object>> filesUrl = (List<Map<String, Object>>) JSON.parse(keywordPositions.toString());
        // 遍历文件列表，提取并存储下载链接
        for (Map<String, Object> stringobjectMap : filesUrl) {
          Map<String, Object> fileResMap = new HashMap<>();
          LOGGER.info(stringobjectMap.get("downloadUrl"));
          fileResMap.put("msg", "签署文件下载成功");
          fileResMap.put("status", 200);
          fileResMap.put("filesUrl", stringobjectMap.get("downloadUrl"));
          if (stringobjectMap.get("fileName") != null && stringobjectMap.get("fileName").toString().contains(".pdf")) {
            LOGGER.info("文件名包含 .pdf");
            fileResMap.put("fileName", stringobjectMap.get("fileName"));
          } else {
            LOGGER.info("文件名不包含 .pdf");
            fileResMap.put("fileName", stringobjectMap.get("fileName")+".pdf");
          }
          resListMap.add(fileResMap);
        }
        return this.ok(resListMap);
      }
    } else {
      // 如果下载链接信息获取失败，则返回错误信息
      fileMap.put("msg", "合同流程非签署完成状态,无法下载文档");
      fileMap.put("status", 500);
      resListMap.add(fileMap);

    }
    // 返回处理结果
    return this.ok(resListMap);
  }

  /**
   * 合同作废
   *
   * @param map
   * @return
   * @throws EsignDemoException
   */
  @POST
  @Path("/delSealPdf")
  @Consumes(MediaType.APPLICATION_JSON)
  public Response delSealPdf(Map<String, Object> map) throws EsignDemoException, BusinessException, SQLException {
    // 从请求参数中提取dataId
    String dataId = StrKit.str(map.get("dataId"));
    ColSummary  colSummary = colManager.getColSummaryByFormRecordId(Long.parseLong(dataId));
    FormBean formBean = cap4FormManager.getForm(colSummary.getFormAppid(), true);
    // 根据数据ID获取表单主数据对象
    FormDataMasterBean formDataMasterBean = cap4FormManager.getDataMasterBeanById(Long.parseLong(dataId), formBean, null);
    // 从流程数据中提取应用ID、应用密钥和合同流程ID
    String appId = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "应用ID")).trim();
    String appSercet = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "应用密钥")).trim();
    String signFlowId = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "合同流程ID")).trim();
    String fileID = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "文件ID")).trim();
    String certifyID = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "认证Id")).trim();
    String startSealPhone = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "发起方手机号")).trim();
    String startOrgName = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "发起方企业名称")).trim();
    String orgName = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "签署方企业名称")).trim();
    String psnAccount = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "签署方手机号")).trim();
    String breakOffReason = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "解约原因")).trim();
    if (!breakOffReason.equals("")) {
      CtpEnumItem usfp = enumManagerNew.getEnumItem(Long.parseLong(breakOffReason));
      breakOffReason = usfp.getValue();

    }
    String breakOffReasonMsg = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "解约说明")).trim();
    Map<String, Object> res = sealManager
        .delSealPdf(signFlowId.trim(), appId.trim(), appSercet.trim(), Arrays.asList(fileID.split(",")), certifyID.trim(), startOrgName.trim(), startSealPhone.trim(), orgName.trim(), psnAccount.trim(),
            breakOffReason, breakOffReasonMsg);

    return this.ok(res);
  }


  /**
   * 认证
   *
   * @param map
   * @return
   * @throws EsignDemoException
   */
  @POST
  @Path("/sealCertify")
  @Consumes(MediaType.APPLICATION_JSON)
  public Response sealCertify(Map<String, Object> map) throws EsignDemoException, BusinessException, SQLException {
    // 从请求参数中提取dataId
    String dataId = StrKit.str(map.get("dataId"));
    ColSummary  colSummary = colManager.getColSummaryByFormRecordId(Long.parseLong(dataId));
    FormBean formBean = cap4FormManager.getForm(colSummary.getFormAppid(), true);
    // 根据数据ID获取表单主数据对象
    FormDataMasterBean formDataMasterBean = cap4FormManager.getDataMasterBeanById(Long.parseLong(dataId), formBean, null);
    // 从流程数据中提取应用ID、应用密钥和合同流程ID
    String appId = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "应用ID")).trim();
    String appSercet = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "应用密钥")).trim();
    String startOrgName = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "发起方企业名称")).trim();
    String startSealPhone = StrKit.str(FormCap4Kit.getFieldValue(formDataMasterBean, "发起方手机号")).trim();
    Map<String, Object> res = sealManager.sealCertify(appId.trim(), appSercet.trim(), startOrgName.trim(), startSealPhone.trim());
    return this.ok(res);
  }


  /**
   * e签宝回调（废弃）
   *
   * @param map
   * @return
   * @throws EsignDemoException
   */
  @POST
  @Path("/notifiySealPdf")
  @Consumes(MediaType.APPLICATION_JSON)
  public Map<String, Object> notifiySealPdf(Map<String, Object> map) throws BusinessException {
    LOGGER.info("notifiySealPdf接收参数值：" + JSON.toJSONString(map));
    JSONObject selectKeyWords = JSONObject.parseObject(JSON.toJSONString(map));
    Object operator = selectKeyWords.get("operator");
    LOGGER.info(JSON.toJSONString(operator));
    JSONObject parse = (JSONObject) JSONObject.parse(JSON.toJSONString(operator));
    LOGGER.info(JSON.toJSONString(parse.get("psnAccount")));
    Map<String, Object> psnAccountMap = (Map<String, Object>) parse.get("psnAccount");
    LOGGER.info(map.get("accountMobile"));
    Long accountId = orgManager.getAllAccounts().get(0).getId();
    V3xOrgMember v3xOrgMember = orgManager.getMembersByMobile(psnAccountMap.get("accountMobile").toString(), accountId);
    LOGGER.info(v3xOrgMember.getId());
    Map<String, Object> resMap = new HashMap<>();
    resMap.put("code", "200");
    resMap.put("msg", "success");
    return resMap;
  }

}
